#!/usr/bin/env python
# coding: utf-8

# Copyright (c) 2020 CSTCHC Technologies Co., Ltd.
# cstc-hardware-cap is licensed under the Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#     http://license.coscl.org.cn/MulanPSL2
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
# PURPOSE.
# See the Mulan PSL v2 for more details.
# Create: 2020-04-01

import re
import os
import time
from .command import Command


def filter_char(string):
    """
    fileter char
    :param string:
    :return:
    """
    ascii_blacklist = map(chr, range(9) + range(11, 13) + range(14, 32))
    filtered = u''
    start = 0
    for i in range(len(string)):
        char_filter = string[i]
        if char_filter in ascii_blacklist or (type(string) != unicode and ord(char_filter) >= 128):
            if start < i:
                filtered += string[start:i]
            start = i + 1
    filtered += string[start:]
    return filtered


class CertDevice:
    """
    Certified device
    """
    port_devices = {}
    qua_pcis = {}

    def __init__(self):
        self.devices = None

    def get_devices(self):
        """
        get devices information
        :return:
        """
        self.devices = list()
        try:
            pipe = Command("udevadm info --export-db")
            pipe.start()
            properties = dict()
            while True:
                line = pipe.readline()
                if line:
                    if line == "\n":
                        if len(properties) > 0:
                            device = Device(properties)
                            if device.path != "":
                                self.devices.append(device)
                            properties = dict()
                    else:
                        prop = line.split(":", 1)
                        if len(prop) == 2:
                            tp = prop[0].strip('\ \'\n')
                            attribute = prop[1].strip('\ \'\n')
                            if tp == "E":
                                keyvalue = attribute.split("=", 1)
                                if len(keyvalue) == 2:
                                    properties[keyvalue[0]] = keyvalue[1]
                            elif tp == "P":
                                properties["INFO"] = attribute
                else:
                    break
        except Exception as e:
            print("Warning: get devices fail")
            print(e)
        self.devices.sort(key=lambda k: k.path)
        return self.devices


class Device:
    """
    get device properties
    """
    def __init__(self, properties=None):
        self.path = ""
        if properties:
            self.properties = properties
            self.path = properties["DEVPATH"]
        else:
            self.properties = dict()

    def get_property(self, prop):
        """
        get properties
        :param prop:
        :return:
        """
        try:
            return self.properties[prop]
        except KeyError:
            return ""

    def block_pci(self):
        pcis = []
        for root,dirs,files in os.walk("/sys/block"):
            for dir in dirs:
                pci = os.path.realpath(os.path.join(root, dir))
                pci = pci.split("/host")[0].split('/')[-1]
                pcis.append(pci)
        return pcis
    
    def get_pci(self):
        """
        card pci
        """
        if "PCI_SLOT_NAME" in self.properties.keys():
            return self.properties["PCI_SLOT_NAME"]
        elif "INTERFACE" in self.properties.keys():
            return self.properties["DEVPATH"].split("/")[-3]
        elif self.path:
            if "end" in self.properties["DEVPATH"]:
                return self.properties["DEVPATH"].split("/host")[0].split('/')[-1]
            else:
                return self.properties["DEVPATH"].split("/")[4]

    def get_name(self):
        """
        card name
        """
        if "ID_PCI_SUBCLASS_FROM_DATABASE" in self.properties.keys():
            card_name = self.properties["ID_MODEL_FROM_DATABASE"]
            if "(" in card_name:
                card_id = card_name[:card_name.index("(")]
            else:
                card_id = card_name
            card_id = "-".join(card_id.split())
            return card_id

    def get_port(self):
        """
        card partition or card network_port
        """
        if "INTERFACE" in self.properties.keys():
            return self.properties["INTERFACE"]
        elif "DEVNAME" in self.properties.keys():
            return self.properties["DEVNAME"].split("/")[-1]
    
    def get_quadruples(self):
        """
        get card quadruple
        """
        quadruples = {}
        if "PCI_SUBSYS_ID" in self.properties.keys() and \
                "PCI_ID" in self.properties.keys():
                    PCI_ID = self.properties["PCI_ID"].lower().split(":")
                    PCI_SUBSYS_ID = self.properties["PCI_SUBSYS_ID"].lower().split(":")
                    quadruples = {"vendorID":PCI_ID[0],"deviceID":PCI_ID[1], \
                            "svID":PCI_SUBSYS_ID[0],"ssID":PCI_SUBSYS_ID[1]}
                    return quadruples
